from decimal import Decimal
from os import path

from alipay import AliPay, AliPayException
from app import settings
from libs import time_helper

PEM_BASE_DIR = path.join(settings.BASE_DIR, *['app', 'pem', 'ali'])
PRIVATE_PATH = path.join(PEM_BASE_DIR, 'app_private_key.pem')
PUBLIC_PATH = path.join(PEM_BASE_DIR, 'alipay_public_key.pem')
# 获取公私钥字符串
APP_ID = '2021002170631198'
app_private_key_string = open(PRIVATE_PATH).read()
alipay_public_key_string = open(PUBLIC_PATH).read()


def get_alipay(debug):
    try:
        return AliPay(
            appid=APP_ID,
            app_notify_url=None,  # 默认回调url
            app_private_key_string=app_private_key_string,
            alipay_public_key_string=alipay_public_key_string,
            sign_type="RSA2",
            debug=debug,  # 上线则改为False , 沙箱True
        )
    except Exception as e:
        print('初始化支付宝支付异常', e)
        return None


# https://opendocs.alipay.com/open/02e7gm
class Ali:
    ali = None

    def __init__(self, debug=False):
        self.ali = get_alipay(debug)

    '''
    {
        'code': '40004',
        'msg': 'Business Failed',
        'sub_code': 'ACQ.PAYMENT_AUTH_CODE_INVALID',
        'sub_msg': '支付失败，获取顾客账户信息失败，请顾客刷新付款码后重新收款，如再次收款失败，请联系管理员处理。[SOUNDWAVE_PARSER_FAIL]',
        'buyer_pay_amount': '0.00',
        'invoice_amount': '0.00',
        'point_amount': '0.00',
        'receipt_amount': '0.00'
    }
    {
        'code': '10000',
        'msg': 'Success',
        'buyer_logon_id': 'plf***@126.com',
        'buyer_pay_amount': '0.01',
        'buyer_user_id': '2088002096099652',
        'fund_bill_list': [{'amount': '0.01', 'fund_channel': 'PCREDIT'}],
        'gmt_payment': '2021-10-15 13:55:24',
        'invoice_amount': '0.01',
        'out_trade_no': 'ali_order_id2',
        'point_amount': '0.00',
        'receipt_amount': '0.01',
        'total_amount': '0.01',
        'trade_no': '2021101522001499651447895830'
    }
    '''

    def barcodePay(self, auth_code, out_trade_no, fen, desc='', opt=None):
        if opt is None:
            opt = {}
        scene = 'bar_code'
        trade_no = ''
        tp_resp = None
        result_code = 'FAIL'
        try:
            yuan = str((Decimal(fen) / Decimal(100)).quantize(Decimal('0.00')))
            time_expire = time_helper.ts_to_time_str(None, '%Y-%m-%d %H:%M:%S', 1800)
            opt.update({'total_amount': yuan, 'time_expire': time_expire})
            tp_resp = self.ali.api_alipay_trade_pay(out_trade_no, scene, auth_code, desc, **opt)

            if type(tp_resp) is dict:
                tp_resp_code = tp_resp.get('code', '')
                if tp_resp_code == '10000':
                    trade_no = tp_resp.get('trade_no', '')
                    result_code = 'SUCCESS'
                    return result_code, trade_no, tp_resp, None
                elif tp_resp_code == '10003':
                    trade_no = tp_resp.get('trade_no', '')
                    return '', trade_no, tp_resp, 'order success pay inprocess'
                else:
                    err = tp_resp.get('sub_msg', '支付宝支付错误')
                    return result_code, trade_no, tp_resp, err
            else:
                err = '支付宝响应错误'
        except AliPayException as e:
            err = e.to_unicode()
        except Exception as e:
            print(e)
            err = '支付异常'
        return result_code, trade_no, tp_resp, err

    """
    {
        "code":"10000",
        "msg":"Success",
        "buyer_logon_id":"282***@qq.com",
        "buyer_user_id":"2088002843561148",
        "fund_change":"Y",
        "gmt_refund_pay":"2021-10-21 20:13:46",
        "out_trade_no":"211020201832541906B0E4M",
        "refund_detail_item_list":[
            {
                "amount":"0.10",
                "fund_channel":"COUPON"
            }
        ],
        "refund_fee":"0.10",
        "send_back_fee":"0.10",
        "trade_no":"2021102022001461145710620216"
    }
    """

    def refund(self, refund_fee, out_trade_no, refund_desc='', out_refund_no=None, ali_trade_no=None, opt=None):
        if opt is None:
            opt = {}
        refund_id = ''
        tp_resp = {}
        try:
            if out_refund_no is None:
                out_refund_no = out_trade_no + 'R'
            opt.update({'out_request_no': out_refund_no})
            if refund_desc != '':
                opt.update({'refund_reason': refund_desc})
            yuan = str((Decimal(refund_fee) / Decimal(100)).quantize(Decimal('0.00')))
            tp_resp = self.ali.api_alipay_trade_refund(yuan, out_trade_no=out_trade_no, trade_no=ali_trade_no, **opt)
            if type(tp_resp) is dict:
                if tp_resp.get('code', '') == '10000':
                    refund_id = tp_resp.get('out_trade_no', '')
                    return refund_id, tp_resp, None
                else:
                    err = tp_resp.get('sub_msg', '支付宝支付错误')
                    return refund_id, tp_resp, err
            else:
                err = '支付宝响应错误'
        except AliPayException as e:
            err = e.to_unicode()
        except Exception as e:
            print(e)
            err = '支付异常'
        return refund_id, tp_resp, err

    """
    {
        'code': '40004',
        'msg': 'Business Failed',
        'sub_code': 'ACQ.TRADE_NOT_EXIST',
        'sub_msg': '交易不存在',
        'buyer_pay_amount': '0.00',
        'invoice_amount': '0.00',
        'out_trade_no': 'order_sn',
        'point_amount': '0.00',
        'receipt_amount': '0.00'
    }
    {
        'code': '10000',
        'msg': 'Success',
        'buyer_logon_id': '282***@qq.com',
        'buyer_pay_amount': '0.00',
        'buyer_user_id': '2088002843561148',
        'invoice_amount': '0.00',
        'out_trade_no': '211020201832541906B0E4M',
        'point_amount': '0.00',
        'receipt_amount': '0.00',
        'send_pay_date': '2021-10-20 20:18:38',
        'total_amount': '0.10',
        'trade_no': '2021102022001461145710620216',
        'trade_status': 'TRADE_CLOSED'
    }
    """

    def queryOrder(self, out_trade_no=None, trade_no=None):
        err = None
        res = {}
        traded_no = ''
        trade_state = ''
        try:
            res = self.ali.api_alipay_trade_query(out_trade_no=out_trade_no, trade_no=trade_no)
            trade_state = res.get('trade_status', '')
            traded_no = res.get('trade_no', '')
        except Exception as e:
            err = '支付订单查询异常'
            print(err, e)
        return traded_no, trade_state, res, err
